﻿using System;
using System.Collections.Generic;
using Ewk.Runtime.Serialization.PositionBased;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ewk.Runtime.Serialization;

namespace Ewk.Runtime.Serialization.UnitTests.PositionBased
{
    /// <summary>
    /// Summary description for PositionBasedDatarecordAttribute
    /// </summary>
    [TestClass]
    public class PositionBasedDatarecordAttributeTests
    {
        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void PositionBasedDatarecordAttribute_is_an_Attribute()
        {
            var attribute = newInstance();
            Assert.IsInstanceOfType(attribute, typeof(Attribute));
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void PositionBasedDatarecordAttribute_cannot_be_initialized_with_a_negative_length_parameter()
        {
            new PositionBasedDatarecordAttribute(-1);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void PositionBasedDatarecordAttribute_cannot_be_initialized_with_a_zero_length_parameter()
        {
            new PositionBasedDatarecordAttribute(0);
        }

        [TestMethod, ExpectedException(typeof(DatarecordOverflowException))]
        public void PositionBasedDatarecordAttribute_cannot_deserialize_a_record_that_is_longer_than_defined()
        {
            var attribute = new PositionBasedDatarecordAttribute(1);
            attribute.Deserialize<object>("12", new List<PositionBasedDatafieldAttribute>());
        }

        [TestMethod]
        public void PositionBasedDatarecordAttribute_can_deserialize_a_record_that_is_longer_than_defined_when_subscribed_to_the_DatarecordOverflow_event()
        {
            string eventMessage = null;
            var attribute = new PositionBasedDatarecordAttribute(1);
            attribute.DatarecordOverflow += delegate(object sender, DatarecordOverflowEventArgs args)
                                                {
                                                    eventMessage = args.Message;
                                                };

            var result = attribute.Deserialize<object>("12", new List<PositionBasedDatafieldAttribute>());

            Assert.IsInstanceOfType(eventMessage, typeof(string));
            Assert.IsNotNull(result);
        }

        [TestMethod]
        public void PositionBasedDatarecordAttribute_can_deserialize_a_record_that_is_longer_than_defined_if_overflow_is_allowed()
        {
            var attribute = new PositionBasedDatarecordAttribute(1)
                                {LengthCriterium = DatarecordLengthCriterium.GreaterThanDefinition};
            var result = attribute.Deserialize<object>("12", new List<PositionBasedDatafieldAttribute>());

            Assert.IsNotNull(result);
        }

        [TestMethod, ExpectedException(typeof(DatarecordIncompleteException))]
        public void PositionBasedDatarecordAttribute_cannot_deserialize_a_record_that_is_shorter_than_defined()
        {
            var attribute = new PositionBasedDatarecordAttribute(3);
            attribute.Deserialize<object>("12", new List<PositionBasedDatafieldAttribute>());
        }

        [TestMethod]
        public void PositionBasedDatarecordAttribute_can_deserialize_a_record_that_is_shorter_than_defined_when_subscribed_to_the_DatarecordIncomplete_event()
        {
            string eventMessage = null;
            var attribute = new PositionBasedDatarecordAttribute(3);
            attribute.DatarecordIncomplete += delegate(object sender, DatarecordIncompleteEventArgs args)
                                                  {
                                                      eventMessage = args.Message;
                                                  };

            var result = attribute.Deserialize<object>("12", new List<PositionBasedDatafieldAttribute>());

            Assert.IsInstanceOfType(eventMessage, typeof(string));
            Assert.IsNotNull(result);
        }

        [TestMethod]
        public void PositionBasedDatarecordAttribute_cannot_deserialize_a_record_that_is_shorter_than_defined_if_incomplete_is_allowed()
        {
            var attribute = new PositionBasedDatarecordAttribute(3)
                                {LengthCriterium = DatarecordLengthCriterium.SmallerThanDefinition};
            var result = attribute.Deserialize<object>("12", new List<PositionBasedDatafieldAttribute>());

            Assert.IsNotNull(result);
        }

        static PositionBasedDatarecordAttribute newInstance()
        {
            return new PositionBasedDatarecordAttribute(1);
        }
    }
}
